<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/3/20
 * Time: 11:46
 */

namespace app\queue\batchgenerateplan;

use app\common\lib\Common;
use app\common\lib\MoyinTts;
use app\common\lib\RedisQueue;
use app\common\lib\TencentTts;
use app\exception\IndexException;
use app\model\image\ImageCommandPlanModel;
use app\model\image\ImageModelModel;
use app\model\novel\NovelChapterModel;
use app\model\novel\NovelChapterPartModel;
use app\model\novel\NovelSpreadModel;
use app\model\plan\PromotionPlanModel;
use app\model\queue\AiImageRequestQueueModel;
use app\model\redis\RedisQueueModel;
use app\model\tencent\TimbreModel;
use app\model\novel\NovelPlanRoleModel;
use support\Cache;
use support\Db;
use Webman\RedisQueue\Consumer;
use app\common\lib\TencentCos;

class BatchGeneratePlan  implements Consumer
{
    // 要消费的队列名
    public $queue = 'batchGeneratePlan';

    // 连接名，对应 plugin/webman/redis-queue/redis.php 里的连接`
    public $connection = 'default';

    protected $resultData = [];

    // 消费
    public function consume($data)
    {
        Common::initQueueConfig();

        $queue = RedisQueueModel::getInstance()->find($data['queueid']);
        $queue->exec_time = date('Y-m-d H:i:s');
        $queue->save();

        try{
            // 无需反序列化
            //var_export($data);
            //var_export('redis_queue_asyncUploadVideo');
            $result = $this->handle($data);

            RedisQueue::getInstance()->saveQueue($this->queue,$data,$result);
        }catch (\Throwable $e){

            RedisQueue::getInstance()->saveQueue($this->queue,$data,['error'=>$e->getMessage()]);
            Common::queueExecptionReport($queue,$data,$e);
        }
    }

    protected function handle($data)
    {
        $novelIds = $data['novel_ids'];
        $commandId = $data['ai_image_command_id'];
        $prefix = $data['prefix'];

        $imageCommand = ImageCommandPlanModel::getInstance()->find($commandId);
        if ($imageCommand == false) {
            throw new IndexException(4020,'生图指令不存在');
        }
        $where      = [['id','in',$novelIds], 'isdel' => 0];
        $novelData = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('created_at', 'asc')->get()->toArray();

        $textLog = [];
        foreach ($novelData as $novel) {
            $novel['title'] = ($prefix?$prefix.'-':'').$novel['title'];
            $novel['ai_image_command_id'] = $commandId;
            $chapterData = NovelChapterModel::getInstance()->getWhere(['novel_sn' => $novel['novel_sn'], 'isdel' => 0])->get();
            foreach ($chapterData as $chapter) {
                $updateChapter = [];

                //todo 1-1 总结原文
                if (empty($chapter['original_content'])) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-original_content 是空值跳过';
                    continue;
                }
                if (empty($chapter['original_content_ai_command'])) {
                    $chapter['original_content_ai_command'] = getAiCommand('original_content_ai_command');
                }

                $analyzeContent = '';
                if(empty($chapter['analyze_content'])){
                    try {
                        $replaceStr     = [
                            "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                            '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                        ];
                        $contentText    = str_replace($replaceStr, "", $chapter['original_content']);
                        $analyzeContent = Common::generatedContent($contentText, $chapter['original_content_ai_command']);
                    } catch (\Throwable $e) {}

                    if ($analyzeContent == false) {
                        $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-总结原文失败跳过';
                        continue;
                    }

                    $updateChapter['analyze_content'] = $analyzeContent;
                    $updateChapter['original_content_ai_command'] = $chapter['original_content_ai_command'];
                }else{
                    $analyzeContent = $chapter['analyze_content'];
                }
                if(empty($analyzeContent)){
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-总结原文空值跳过';
                    continue;
                }

                //todo 1-2 总结内容分段
                if (empty($chapter['content_parts_ai_command'])) {
                    $chapter['content_parts_ai_command'] = getAiCommand('content_parts_ai_command');
                }
                $content  = '';
                $contents = '';
                if(empty($chapter['content'])){
                    foreach ([1, 2, 3] as $n) {
                        try {
                            $replaceStr  = [
                                "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                                '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                            ];
                            $contentText = str_replace($replaceStr, "", $analyzeContent);
                            $content     = Common::generatedContent($contentText, $chapter['content_parts_ai_command']);
                        } catch (\Throwable $e) {}
                        if ($content == false) {
                            continue;
                        }

                        $contents = array_values(array_filter(explode("\n", $content)));
                        $lk       = 0;
                        foreach ($contents as $text) {
                            if (mb_strlen($text) <= 5) {
                                $lk++;
                            }
                        }
                        if ($lk >= 3) {
                            $content  = '';
                            $contents = [];
                            continue;
                        } else {
                            //满足跳出
                            break;
                        }
                    }
                    if ($contents == false) {
                        $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-分析内容分段失败跳过';
                        continue;
                    }

                    $updateChapter['content'] = implode("\n",$contents);
                    $updateChapter['content_parts_ai_command'] = $chapter['content_parts_ai_command'];
                }else{
                    $contents = explode("\n",$chapter['content']);
                }
                if(empty($contents)){
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-分析内容分段空值跳过';
                    continue;
                }

                //todo 1-3 批量生成描述词
                if (empty($chapter['batch_prompt_ai_command'])) {
                    $chapter['batch_prompt_ai_command'] = getAiCommand('batch_prompt_ai_command');
                }
                if (empty($chapter['gptversion'])) {
                    $chapter['gptversion'] = config('param.default_gpt_version', 'gpt-4o');
                }

                $promptContent  = '';
                $promptContents = [];
                if(empty($chapter['prompt_content'])){
                    foreach ([1, 2, 3] as $n) {
                        try {
                            $contentData = [];
                            foreach ($contents as $k => $contentV) {
                                $contentData[] = (($k + 1) . '.') . preg_replace('/^\d+[\.]*/', '', $contentV);
                            }
                            $contentText   = implode("\n", $contentData);
                            $batchPromptAiCommand = str_replace(['@parts'],[count($contentData)],$chapter['batch_prompt_ai_command']);
                            $promptContent = Common::generatedBatchPrompt($contentText, $batchPromptAiCommand, $chapter['gptversion']);
                        } catch (\Throwable $e) {
                        }
                        if ($promptContent == false) {
                            continue;
                        }
                        $promptContents = array_values(array_filter(explode("\n", $promptContent)));

                        if (count($contents) != count($promptContents)) {
                            $promptContent  = '';
                            $promptContents = [];
                            //段落不一致，跳过
                            continue;
                        } else {
                            //满足跳出
                            break;
                        }
                    }
                    if (count($contents) != count($promptContents)) {
                        $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-批量生成描述词段落不一致跳过';
                        //段落不一致，跳过
                        continue;
                    }

                    $updateChapter['prompt_content'] = implode("\n",$promptContents);
                    $updateChapter['batch_prompt_ai_command'] = $chapter['batch_prompt_ai_command'];
                    $updateChapter['gptversion'] = $chapter['gptversion'];
                }else{
                    $promptContents = explode("\n",$chapter['prompt_content']);
                }
                if(empty($promptContents)){
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-批量生成描述词段落空值跳过';
                    continue;
                }

                //todo 2 创建方案并更新章节内容
                $planId = false;
                try {
                    Db::connection('mysql')->beginTransaction();
                    $planId = $this->createPlan($novel, $chapter);
                    if ($planId) {
                        $updateChapter && NovelChapterModel::getInstance()->getWhere(['id' => $chapter['id']])->update($updateChapter);

                        NovelSpreadModel::getInstance()->getWhere(['id' => $novel['id']])->update(['status' => 1]);
                    }
                    Db::connection('mysql')->commit();
                } catch (\Throwable $e) {
                    Db::connection('mysql')->rollBack();
                }
                if ($planId == false) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-方案生成失败跳过';
                    continue;
                }

                $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-加入生成分段的队列';
                //todo 3 加入自动生成分段的队列
                //生成唯一的请求id
                $requestId = Common::getRequestId();

                // 队列名
                $queue = 'asyncPlanPart';
                // 数据，可以直接传数组，无需序列化
                $data = ['requestid' => $requestId, 'planid' => $planId, 'type' => 'all', 'from' => 'cron'];
                // 投递消息
                RedisQueue::getInstance()->sendQueue($queue, $data);

                //延迟20毫秒
                usleep(20000);
            }
        }

        return $textLog;
    }

    protected function createPlan($novel, $chapter)
    {
        $imageCommand = ImageCommandPlanModel::getInstance()->find($novel['ai_image_command_id']);
        if ($imageCommand == false) {
            return false;
        }
        $insertPlan = [
            'name'                  => $novel['title'] .'-'. $imageCommand['name'],
            'chapterid'             => $chapter['id'],
            'novel_sn'              => $chapter['novel_sn'],
            'musicid'               => 0,
            'timbreid'              => 92,
            'music_volume'          => 50,
            'timbre_volume'         => 50,
            'speak_speed'           => 13,
            'fontid'                => 48,
            'ai_images_nums'        => 1,
            'ai_image_command'      => $imageCommand['ai_image_command'],
            'ai_image_command_id'   => $imageCommand['id'],
            'ai_image_command_data' => urlencode(str_replace(' ', '~', json_encode($imageCommand->toArray(), 256))),
            'create_way'            => 'admin_batch_' . $novel['ai_image_command_id'],
            'spread_type'            => $novel['spread_type'],
        ];
        $planId     = PromotionPlanModel::getInstance()->insertGetId($insertPlan);

        return $planId;
    }

    // 消费失败回调
    /*
    $package = [
        'id' => 1357277951, // 消息ID
        'time' => 1709170510, // 消息时间
        'delay' => 0, // 延迟时间
        'attempts' => 2, // 消费次数
        'queue' => 'send-mail', // 队列名
        'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
        'max_attempts' => 5, // 最大重试次数
        'error' => '错误信息' // 错误信息
    ]
    */
    public function onConsumeFailure(\Throwable $e, $package)
    {
//        echo "consume failure\n";
//        echo $e->getMessage() . "\n";
//        // 无需反序列化
//        var_export($package);

        RedisQueue::getInstance()->saveQueue($this->queue,$package['data'],['error'=>$e->getMessage()]);
    }

}